﻿// $Id: CacheManager.cs 10 2008-02-29 15:58:02Z mcartoixa $
/*
 *  Copyright (C) 2007 Noury Solutions
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 3 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 */
/*! \file
 * \brief
 *
 * \author $Author: mcartoixa $
 * \date $Date: 2008-02-29 16:58:02 +0100 (ven., 29 févr. 2008) $
 * \version $Revision: 10 $
 */

#if (!NET_CF)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Salamanca.DataAccess;


namespace Salamanca.DataAccess.EnterpriseLibrary.Caching
{



    ///////////////////////////////////////////////////////////////////////////
    ///
    /// <summary>Arguments of the <see cref="CacheManagerAdapter.GeneratingStringKey" /> event.</summary>
    ///
    ///////////////////////////////////////////////////////////////////////////

    public sealed class GeneratingStringKeyEventArgs:
        EventArgs
    {

        /// <summary>Constructor.</summary>
        public GeneratingStringKeyEventArgs(IPrimaryKey key)
        {
            _Key=key;
            GeneratedKey=string.Format(
                CultureInfo.InvariantCulture,
                "{0}_{1}",
                key.GetType(),
                key.Value
            );
        }

        /// <summary>The original key.</summary>
        public IPrimaryKey Key
        {
            get
            {
                return _Key;
            }
        }

        /// <summary>The generated key.</summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
        public string GeneratedKey;

        /// <summary>The original key.</summary>
        private IPrimaryKey _Key;
    }



    ///////////////////////////////////////////////////////////////////////////
    ///
    /// <summary>Base class to implement a <see cref="ICacheManager">cache manager</see> adapter around a web <see cref="Cache" />.</summary>
    ///
    ///////////////////////////////////////////////////////////////////////////

    public class CacheManagerAdapter:
        ICacheManager
    {

        /// <summary>Constructor.</summary>
        public CacheManagerAdapter(Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager cache)
        {
            Debug.Assert(cache!=null);
            if (cache==null)
                throw new ArgumentNullException("cache");

            _Cache=cache;
        }

        /// <summary>Raises the <see cref="CacheManagerAdapter.GeneratingStringKey" /> event.</summary>
        /// <remarks>
        ///   <para>The web <see cref="Cache" /> only accepts string keys. When a string key
        /// is about to be generated for an element, this method is called.</para>
        ///   <para>The string key generated by default is the concatenation of a <include file="../doc/Global.doc.xml" path="doc/template[@name='DomainModel']/*" /> key
        /// <see cref="Type" /> name with the string representation of the key <see cref="IPrimaryKey.Value" />.
        /// If distinct <see cref="IPrimaryKey.Value" />s have the same string representation, you must then either :
        ///     <list type="bullet">
        ///       <item><description>override <see cref="Object.ToString()" /> for the <see cref="IPrimaryKey.Value" /> type so that different values have different string representations.</description></item>
        ///       <item><description>override this method to create a new string key.</description></item>
        ///     </list>
        /// </para>
        /// <include file="../doc/Global.doc.xml" path="doc/template[@name='OnEvent']/*" />
        /// </remarks>
        protected virtual void OnGeneratingStringKey(GeneratingStringKeyEventArgs e)
        {
            if (GeneratingStringKey!=null)
                GeneratingStringKey(this, e);
        }

        private string GetStringKey(IPrimaryKey key)
        {
            GeneratingStringKeyEventArgs args=new GeneratingStringKeyEventArgs(key);
            OnGeneratingStringKey(args);

            return args.GeneratedKey;
        }

        private void Add(string key, IDomainModel value)
        {
            Cache.Add(key, value);
        }

        /// <summary>Adds an element with the provided key and value to the <see cref="CacheManagerAdapter" />.</summary>
        void ICacheManager.Add(object key, object value)
        {
            Add(GetStringKey((IPrimaryKey)key), (IDomainModel)value);
        }

        /// <summary>Removes all keys and values from the <see cref="CacheManagerAdapter" />.</summary>
        void ICacheManager.Clear()
        {
            _Cache.Flush();
        }

        /// <summary>Determines whether the <see cref="CacheManagerAdapter" /> contains an element with the specified key.</summary>
        bool ICacheManager.ContainsKey(object key)
        {
            return _Cache.Contains(GetStringKey((IPrimaryKey)key));
        }

        /// <summary>Removes the element with the specified key from the <see cref="CacheManagerAdapter" />.</summary>
        bool ICacheManager.Remove(object key)
        {
            string sk=GetStringKey((IPrimaryKey)key);
            bool ret=_Cache.Contains(sk);
            _Cache.Remove(sk);
            return ret && !_Cache.Contains(sk);
        }

        /// <summary>Gets the value associated with the specified key.</summary>
        bool ICacheManager.TryGetValue(object key, out object value)
        {
            object v=_Cache.GetData(GetStringKey((IPrimaryKey)key));
            if (v is IDomainModel)
                value=(IDomainModel)v;
            else
                value=null;

            return value!=null;
        }

        /// <summary>Gets or sets the element with the specified key.</summary>
        object ICacheManager.this[object key]
        {
            get
            {
                return _Cache.GetData(GetStringKey((IPrimaryKey)key));
            }
        }

        /// <summary>The adapted web <see cref="CacheManager" />.</summary>
        protected Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager Cache
        {
            get
            {
                return _Cache;
            }
        }

        /// <summary>Event raised when a new string key is about to be generated for an element.</summary>
        public event EventHandler<GeneratingStringKeyEventArgs> GeneratingStringKey;

        /// <summary>The adapted web <see cref="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager" />.</summary>
        private Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager _Cache;
    }
}
#endif
